﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TreeLayoutPlayground
{
    internal partial class InteractiveViewer : Form
    {
        Tree tree;

        public InteractiveViewer()
        {
            InitializeComponent();

            tree = new Tree(50, 50);
            cbLayoutType.SelectedIndex = 0;
        }

        private void updateImage()
        {
            // Layout the Tree with the appropriate engine
            LayoutEngine engine;
            switch (cbLayoutType.SelectedIndex)
            {
                case 1: engine = new CSGLayoutEngine(); break;
                //case 2: engine = new SpringLayoutEngine(); break;
                case 3: engine = new GraphSharpLayoutEngine(); break;
                case 4: engine = new OVPairLayoutEngine(); break;
                case 5: engine = new SpringLayoutEngine2(); break;
                default: engine = new SimpleLayoutEngine(); break;
            }

            engine.GapSize = 16;
            engine.Layout(tree);

            lScore.Text = string.Format("{0:0.00000}", engine.EvaluateArea(tree));
            lLineScore.Text = string.Format("{0:0.00000}", engine.EvaluateLines(tree));

            // Draw the Tree
            Size size = tree.OverallSize;
            Bitmap image = new Bitmap(size.Width, size.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            Graphics graphics = Graphics.FromImage(image);
            graphics.Clear(Color.White);
            if (tree.AntiAliasDrawing) { graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; }
            if (tree.AntiAliasText) { graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; }

            tree.Draw(graphics);

            pbImage.Image = image;
            pbImage.Size = size;
        }

        private void cbLayoutType_SelectedIndexChanged(object sender, EventArgs e)
        {
            // If the layout type was changed then we need to update the layout
            updateImage();
        }

        private void pbImage_MouseClick(object sender, MouseEventArgs e)
        {
            // Find the selected Tree
            Tree selected = tree.SelectTree(new Point(e.X, e.Y));

            // If nothing was selected then don't do anything
            if (selected == null) { return; }

            if (rbAdd.Checked)
            {
                Tree child = new Tree((int)nudWidth.Value, (int)nudHeight.Value);
                // Add a new child to the selected Tree
                // Use the current size
                selected.AddChild(child);
            }
            else if (rbRemove.Checked)
            {
                // Remove the selected Tree unless it is the root
                if (tree == selected) { return; }

                tree.RemoveChild(selected);
            }
            else if (rbResize.Checked)
            {
                // Set the size of the selected tree
                selected.MyBox.Width = (int)nudWidth.Value;
                selected.MyBox.Height = (int)nudHeight.Value;
            }

            // Update the layout
            updateImage();
        }

        private void InteractiveViewer_Resize(object sender, EventArgs e)
        {
            int x = Math.Max(1, ClientRectangle.Right - 12 - pImage.Left);
            int y = Math.Max(1, ClientRectangle.Bottom - 12 - pImage.Top);

            pImage.Size = new Size(x, y);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int MaxHeight = 5;
            int MaxWidth = 20;
            int MaxChildren = 3;

            Random r = new Random();
            Queue<Tree> queue = new Queue<Tree>();
            tree = new Tree((int)nudWidth.Value, (int)nudHeight.Value);
            queue.Enqueue(tree);

            do
            {
                Tree cur = queue.Dequeue();

                if (r.NextDouble() > ((MaxHeight - cur.TreeHeight + 1) / (double)MaxHeight)) { continue; }

                int num = r.Next(1, MaxChildren + 1);
                if (num == 0) { continue; }

                for (; num > 0; num--)
                {
                    Tree t = new Tree((int)nudWidth.Value, (int)nudHeight.Value);
                    cur.AddChild(t);
                    queue.Enqueue(t);
                }
            } while (queue.Count > 0 && tree.TreeHeight < MaxHeight && tree.TreeWidth < MaxWidth);

            updateImage();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                pbImage.Image.Save(saveFileDialog1.FileName);
            }
        }
    }
}
